package com.leyou.item.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.leyou.common.constants.MQConstants;
import com.leyou.common.dto.PageDTO;
import com.leyou.common.entity.Category;
import com.leyou.common.exception.LyException;
import com.leyou.item.dto.SkuDTO;
import com.leyou.item.dto.SpuDTO;
import com.leyou.item.dto.SpuDetailDTO;
import com.leyou.item.entity.Brand;
import com.leyou.item.entity.Sku;
import com.leyou.item.entity.Spu;
import com.leyou.item.entity.SpuDetail;
import com.leyou.item.mapper.SpuMapper;
import com.leyou.item.service.*;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author BaiZY on 2020/8/25.
 * @version 1.0
 */
@Service
public class SpuServiceImpl extends ServiceImpl<SpuMapper, Spu> implements SpuService {
    @Autowired
    private BrandService brandService;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private SkuService skuService;

    @Autowired
    private SpuDetailService spuDetailService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Override
    public PageDTO<SpuDTO> queryByPage(Long bid, Long cid, Long id, Long page, Long rows, Boolean saleable) {
        Page<Spu> info = new Page<>(page, rows);
        page(info, new QueryWrapper<Spu>()
                .eq(bid != null, "brand_id", bid)
                .eq(cid != null, "cid3", cid)
                .eq(id != null, "id", id)
                .eq(saleable != null, "saleable", saleable));

        //查询结果
        long total = info.getTotal();
        long pages = info.getPages();
        List<Spu> records = info.getRecords();

        List<SpuDTO> spuDTOList = SpuDTO.convertEntityList(records);

        for (SpuDTO spuDTO : spuDTOList) {
            handleCategoryAndBrandName(spuDTO);
        }

        //封装结果并返回
        return new PageDTO<>(total, pages, spuDTOList);
    }

    /**
     * 根据id查询spu及sku、spuDetail等
     *
     * @param id
     * @return
     */
    @Override
    public SpuDTO queryGoodsById(Long id) {
        //1.查询spu
        Spu spu = this.getById(id);
        if (spu == null) {
            throw new LyException(400, "商品id不存在");
        }
        SpuDTO spuDTO = new SpuDTO(spu);

        //2.查询spuDetail
        SpuDetail spuDetail = spuDetailService.getById(id);
        if (spuDetail == null) {
            throw new LyException(400, "商品id不存在");
        }

        spuDTO.setSpuDetail(new SpuDetailDTO(spuDetail));

        //3.查询sku
        List<Sku> list = skuService.query().eq("spu_id", id).list();
        if (CollectionUtils.isEmpty(list)) {
            throw new LyException(400, "商品id不存在");
        }
        spuDTO.setSkus(SkuDTO.convertEntityList(list));


        //4.设置商品名称和分类名称
        handleCategoryAndBrandName(spuDTO);
        return spuDTO;
    }

    @Transactional
    @Override
    public void saveGoods(SpuDTO spuDTO) {
        //1.新增Spu
        Spu spu = spuDTO.toEntity(Spu.class);
        spu.setSaleable(false);
        boolean add = this.save(spu);
        if (!add) {
            throw new LyException(500, "新增商品失败");
        }

        //2.新增spuDetail
        SpuDetail spuDetail = spuDTO.getSpuDetail().toEntity(SpuDetail.class);
        spuDetail.setSpuId(spu.getId());
        add = spuDetailService.save(spuDetail);
        if (!add) {
            throw new LyException(500, "新增商品失败");
        }

        //3.新增sku
        List<Sku> list = spuDTO.getSkus().stream().map(skuDTO -> {
            Sku sku = skuDTO.toEntity(Sku.class);
            sku.setSaleable(false);
            sku.setSpuId(spu.getId());
            return sku;
        }).collect(Collectors.toList());

        //4.批量新增
        skuService.saveBatch(list);
    }

    @Transactional
    @Override
    public void updateSpuSaleable(Long id, Boolean saleable) {
        //1.更新spu
        Spu spu = new Spu();
        spu.setId(id);
        spu.setSaleable(saleable);
        boolean update = updateById(spu);
        if (!update) {
            throw new LyException(500, "更新失败");
        }

        //2.更新sku
        Sku sku = new Sku();
        sku.setSaleable(saleable);
        update = skuService.update(sku, new QueryWrapper<Sku>().eq("spu_id", id));
        //update = skuService.update().eq("spu_id", id).set("saleable", saleable).update();

        if (!update) {
            throw new LyException(500, "更新失败");
        }

        String routingKey = saleable ? MQConstants.RoutingKeyConstants.ITEM_UP_KEY : MQConstants.RoutingKeyConstants.ITEM_DOWN_KEY;

        amqpTemplate.convertAndSend(MQConstants.ExchangeConstants.ITEM_EXCHANGE_NAME, routingKey, id);
    }

    /**
     * 更新商品
     *
     * @param spuDTO
     */
    @Transactional
    @Override
    public void updateGoods(SpuDTO spuDTO) {

        Long id = spuDTO.getId();
        if (id != null) {
            //1.更新spu
            Spu spu = spuDTO.toEntity(Spu.class);
            boolean success = updateById(spu);
            if (!success) {
                throw new LyException(500, "更新失败");
            }
        }

        //2.更新spuDetail
        SpuDetailDTO spuDetailDTO = spuDTO.getSpuDetail();
        if (spuDetailDTO != null && spuDetailDTO.getSpuId() != null) {
            SpuDetail spuDetail = spuDetailDTO.toEntity(SpuDetail.class);
            //Long spuId = spuDetail.getSpuId();
            //boolean success = spuDetailService.update(spuDetail, new UpdateWrapper<SpuDetail>().eq("spu_id", spuId));
            boolean success = spuDetailService.updateById(spuDetail);
            if (!success) {
                throw new LyException(500, "更新失败");
            }
        }

        //3.更新sku
        List<SkuDTO> skuDTOS = spuDTO.getSkus();

        if (CollectionUtils.isEmpty(skuDTOS)) {
            return;
        }

        // 3.1转换DTO，并将sku根据saleable是否为null来分组。null，是新增或修改，不是null是删除
        Map<Boolean, List<Sku>> map = skuDTOS.stream()
                .map(skuDTO -> skuDTO.toEntity(Sku.class))
                .collect(Collectors.groupingBy(sku -> sku.getSaleable() == null));

        //3.2 获取新增或者要修改的sku
        List<Sku> insertList = map.get(true);
        if (!CollectionUtils.isEmpty(insertList)) {
            skuService.saveOrUpdateBatch(insertList);
        }

        //3.3 获取要删除的sku
        List<Sku> delList = map.get(false);
        if (!CollectionUtils.isEmpty(delList)) {
            List<Long> ids = delList.stream().map(Sku::getId).collect(Collectors.toList());
            skuService.removeByIds(ids);
        }
    }

    private void handleCategoryAndBrandName(SpuDTO spuDTO) {
        // 根据品牌id查询品牌名称
        Brand brand = brandService.getById(spuDTO.getBrandId());
        if (brand != null) {
            spuDTO.setBrandName(brand.getName());
        }

        // 根据三级分类id查询分类集合
        List<Category> categories = categoryService.listByIds(spuDTO.getCategoryIds());

        if (!CollectionUtils.isEmpty(categories)) {
            // 取出分类的名称，拼接起来
            String names = categories
                    .stream()
                    .map(Category::getName)
                    .collect(Collectors.joining("/"));
            spuDTO.setCategoryName(names);
        }
    }
}
